package com.haotian.redis.base;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import redis.clients.jedis.Jedis;

public class RedisSentinelAndSimpleBaseHash extends RedisSentinelAndSimpleBase {

	private final String LOCK_FUX_ = "LOCK:";

	/**
	 * 阻塞获得锁
	 * 
	 * @param key
	 * @return
	 * @throws InterruptedException
	 * @
	 */
	public final void lock(String key) throws InterruptedException {
		String lockkey = LOCK_FUX_ + key;
		try (Jedis jedis = getJedis();) {
			//如果 ==0 代表存在 进入循环 等待获取锁
			while (jedis.setnx(lockkey, String.valueOf(System.currentTimeMillis() + 5000)) == 0) {
				//当前时间大于过期时间的前提下 必须大于 旧的值 并同时设置新的值如果不大于旧的值证明被其他机器并行设置了，则继续等待锁释放或过期
				if (System.currentTimeMillis() > Long.valueOf(jedis.get(lockkey)) && System.currentTimeMillis() > Long
						.valueOf(jedis.getSet(lockkey, String.valueOf(System.currentTimeMillis() + 5000)))) {
					break;
				}
				try {
					Thread.sleep(250);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 释放锁
	 * 
	 * @param key
	 * @return @
	 */
	public final void reLock(String key) {
		key = LOCK_FUX_ + key;
		this.del(key);
	}

	/**
	 * 检查key是否已经存在
	 * 
	 * @param key
	 * @return @
	 */
	public final boolean exists(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.exists(key);
		}
	}

	/**
	 * 检查key是否已经存在
	 * 
	 * @param key
	 * @return @
	 */
	public final boolean exists(byte[] key) {
		try (Jedis jedis = getJedis();) {
			return jedis.exists(key);
		}
	}

	/**
	 * 通过key删除
	 * 
	 * @param key
	 * @
	 */
	public final long del(byte[] key) {
		try (Jedis jedis = getJedis();) {
			return jedis.del(key);
		}
	}

	/**
	 * 通过key删除
	 * 
	 * @param key
	 * @
	 */
	public final long del(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.del(key);
		}
	}

	/**
	 * 存入Object 序列化对象 无超时时间
	 * 
	 * @param key
	 * @param object
	 * @return
	 * @throws IOException
	 * @
	 */
	public final String setObject(byte[] key, Object object) throws IOException {
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();
				ObjectOutputStream oos = new ObjectOutputStream(out);) {
			oos.writeObject(object);
			oos.flush();
			byte[] value = out.toByteArray();
			return this.set(key, value);
		}
	}

	/**
	 * 存入Object 序列化对象 带超时时间
	 * 
	 * @param key
	 * @param object
	 * @return
	 * @throws IOException
	 * @
	 */
	public final String setObject(byte[] key, Object object, int seconds) throws IOException {
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();
				ObjectOutputStream oos = new ObjectOutputStream(out);) {
			oos.writeObject(object);
			oos.flush();
			byte[] value = out.toByteArray();
			return this.set(key, value, seconds);
		}
	}

	public final Object getObject(byte[] key) throws IOException, ClassNotFoundException {
		byte[] buf = this.get(key);
		if (null == buf) {
			return null;
		}
		try (ByteArrayInputStream in = new ByteArrayInputStream(buf);
				ObjectInputStream ois = new ObjectInputStream(in);) {
			return ois.readObject();
		}
	}

	public final String set(byte[] key, byte[] value, int seconds) {
		try (Jedis jedis = getJedis();) {
			return jedis.setex(key, seconds, value);
		}
	}

	public final String set(String key, String value, int seconds) {
		try (Jedis jedis = getJedis();) {
			return jedis.setex(key, seconds, value);
		}
	}

	public final String set(String key, String value) {
		try (Jedis jedis = getJedis();) {
			return jedis.set(key, value);
		}
	}

	public final String set(byte[] key, byte[] value) {
		try (Jedis jedis = getJedis();) {
			return jedis.set(key, value);
		}
	}

	public final String get(String key) {
		try (Jedis jedis = getJedis();) {
			return jedis.get(key);
		}
	}

	public final byte[] get(byte[] key) {
		try (Jedis jedis = getJedis();) {
			return jedis.get(key);
		}
	}

}
